/*! \defgroup execmodel Workflow Execution Model

    Here are classes, which work with ARS workflow execution model. Normally execution model is
    generated from ARS log file and represents log file items in a tree. To generate execution model
    from a log file, ARSLogParser is used.
*/

/*! \file logmodel.h
    \ingroup execmodel
    \brief This file contains declarations for common data objects for ARS execution model.
    \version 1.0

    This model is build from ARS logs. It has a tree structure.
    Normally root of this tree is ARSExecModel object.
*/

#ifndef __LOG_MODEL_H
#define __LOG_MODEL_H

#include <QStandardItemModel>
#include <QHash>
#include <QVector>
#include <QFile>
#include <QDateTime>
#include <QAbstractItemModel>
#include <QSortFilterProxyModel>
#include <QPointer>
#include <QTime>

#include <dynamicmodel.h>

#include "dynamicviewsettings.h"

/*! \class SearchQualification
    \ingroup execmodel
    \brief Provides qualification for items search.

    Search qualification is designed as a property/value pair. If object has property called
        \a propertyName and it's value equals \a propertyValue, it matches qualification. Otherwise
        it doesn't.
*/
class SearchQualification
{
public:
    /*! Creates search qualification with  */
    SearchQualification( const QString propertyName = QString(),
                         QVariant propertyValue = QVariant() );

    /*! Returns property name. */
    QString propertyName() const;

    /*! Sets property name. */
    void setPropertyName( const QString & propertyName );

    /*! Returns property value. */
    QVariant propertyValue() const;

    /*! Sets property value. */
    void setPropertyValue( const QVariant & propertyValue );

    /*! Returns true if item has property called \a propertyName and it's value equals
        \a propertyValueproperty value. Otherwise returns false. */
    bool match( ARSExecItem * item ) const;

private:
    QString m_propertyName;
    QVariant m_propertyValue;
};

/*! Search qualifications list. */
typedef QList<SearchQualification> SearchQualificationList;

/*! SearchQualificationList is declared to use it in QVariant. */
Q_DECLARE_METATYPE(SearchQualificationList);

/*! \class ARSExecModel
    \ingroup execmodel
    \brief Provides a log model.
*/
class TreeViewModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    enum SearchDirection
    {
        Forward,
        Backward
    };

    /*! \enum DataRoles
        Data roles for ARSExecModel items.
    */
    enum DataRoles
    {
        RoleItemData = Qt::UserRole,
        RoleAddComment
    };

    /*! Constructor. */
    TreeViewModel( DynamicModel * model = 0, QObject * parent = 0 );

    /*! Destructor. */
    ~TreeViewModel();

    /*! Returns root item. */
    DynamicModel * dynamicModel();

    /*! Sets the root item to \a item. */
    void setDynamicModel( DynamicModel * model );

    /*! Returns the index of the item in the model specified by the given \a row,
        \a column and \a parent index.
    */
    QModelIndex index( int row, int column,
                       const QModelIndex &parent = QModelIndex() ) const;

    /*! Returns the index of the item in the model specified by the given \a item,
    */
    QModelIndex index( ARSExecItem * item ) const;

    /*! Return execution item corresponding to \a index. */
    static ARSExecItem * item( const QModelIndex & index );

    /*! Returns the parent of the model item with the given \a index,
        or QModelIndex() if it has no parent.
    */
    QModelIndex parent( const QModelIndex & index ) const;

//    static QModelIndex nextIndex( const QModelIndex & index );
//    static QModelIndex previousIndex( const QModelIndex & index );

    /*! Returns the number of rows under the given parent. When the parent is valid
        it means that rowCount is returning the number of children of parent.
    */
    int rowCount( const QModelIndex & parent = QModelIndex() ) const;

    /*! Returns the number of columns for the children of the given parent. */
    int columnCount( const QModelIndex & parent = QModelIndex() ) const;

    /*! Returns the data stored under the given role for the item referred to by the index. */
    QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const;

    bool setData( const QModelIndex &index, const QVariant &value, int role );

    /*! Insert new item before \a row. */
    bool insertRows(int row, int count, const QModelIndex &parent);

    Qt::ItemFlags flags( const QModelIndex & index ) const;

    QModelIndex search( const SearchQualificationList qualification, ARSExecItem * item,
                        SearchDirection direction );

    static bool indexLessThen( const QModelIndex & index1, const QModelIndex & index2 );
    static bool itemLessThen( ARSExecItem * item1, ARSExecItem * item2 );
    static void sortIndexList( QModelIndexList * list );
    static int insertIndexInList( QModelIndexList * list, const QModelIndex & index );
    static ARSExecItemList itemPath( ARSExecItem * item );
    void setTreeViewHeight( int height );

    /*! Returns model index. */
    ObjectsIndex * index() const;

private:
    DynamicModel * m_model;
    int m_treeViewHeight;
};

/*! \class DebugFilterProxyModel
    \ingroup execmodel
    \brief Provides a log model filtering model.
*/
class TreeViewFilterProxyModel : public QSortFilterProxyModel
{
    Q_OBJECT

public:
    enum FilterMode
    {
        ShowAllWorkflow,
        HideEmptyWorkflow,
        HideInternalWorkflow
    };

    /*! Create proxy model. */
    TreeViewFilterProxyModel( FilterMode filterMode, QObject * parent = 0 );

    /*! Returns true if \a source_parent child item at \a source_row matches current filter condition.
        Otherwise returns false. */
    bool filterAcceptsRow( int source_row, const QModelIndex & source_parent )const;

    bool itemAccepted( ARSExecItem * item ) const;

    /*! Hides workflow objects and workflow blocks without child items. */
    void setShowEmptyWorkflow( bool show );

    /*! Hides workflow objects and workflow blocks without child items. */
    void setActionsFilter( ARSExecAction::ActionType actions );

    void setDocViewActive( bool active );

    bool isExternal(ARSExecItem * item) const;

private:
    bool m_showEmptyWorkflow;
    bool m_docViewActive;
    ARSExecAction::ActionType m_actionsMask;
    FilterMode m_filterMode;
};

#endif // __LOG_MODEL_H 
